/**
 * 项目打包操作
 * 复制除了js的文件
 * js文件进行压缩
 */

const path = require("path");
const fs = require("fs");
const glob = require("glob");
const makeDir = require("make-dir");
const UglifyJS = require("uglify-js");
const copyFile = require("fs-copy-file");
const CleanCSS = require("clean-css");
const htmlMinifier = require("html-minifier");
const Postcss = require("postcss");
const postcssPresetEnv = require("postcss-preset-env");
const htmlparser2 = require("htmlparser2");
// 设置插件
const processor = Postcss([
  postcssPresetEnv({
    stage: 2,
    browsers: ["> 0%", "Android 2.3", "iOS 3.2", "Safari 3.1", "IE 10"] //支持大多数浏览器
  })
]);

/** 分割 */
function splitFileType(path) {
  path = path || "";
  const list = path.split(".");
  return list;
}

/** 表示是js文件 */
function isJsFile(path) {
  const list = splitFileType(path);
  if (list.length <= 1) return false;
  if (list[list.length - 1] === "js") return true;
  return false;
}
/** 表示是css文件 */
function isCssFile(path) {
  const list = splitFileType(path);
  if (list.length <= 1) return false;
  if (list[list.length - 1] === "css") return true;
  return false;
}
/** 表示是html文件 */
function isHtmlFile(path) {
  const list = splitFileType(path);
  if (list.length <= 1) return false;
  if (list[list.length - 1] === "art") return true;
  if (list[list.length - 1] === "html") return true;
  return false;
}
/** 格式化css */
async function formatCss(css, isHtml) {
  if (isHtml) {
    // html的话要先解析出css
    let isCssTag;
    let cssStringList = []; //css字符串
    const parser = new htmlparser2.Parser({
      onopentag(name) {
        if (name === "style") {
          isCssTag = true;
        } else {
          isCssTag = false;
        }
      },
      onclosetag(name) {
        if (name === "style") {
          isCssTag = false;
        }
      },
      ontext(text) {
        if (!isCssTag || !text) return;
        cssStringList.push(text);
      }
    });
    parser.write(css);
    await Promise.all(
      cssStringList.map((item) => {
        return processor.process(item, { from: undefined }).then((result) => {
          if (!result.css) return;
          css = css.replace(item, result.css);
        });
      })
    );
    parser.end();
    return css;
  } else {
    return processor.process(css, { from: undefined }).then((result) => {
      return result.css || css;
    });
  }
}

console.log("biuld start:----------");
console.time();
process.on("exit", () => {
  console.log("biuld end:----------");
  console.timeEnd();
});
// 遍历文件
glob(
  "**/*",
  {
    ignore: ["node_modules/**", "dist/**", "biuld.js", ".git/**"],
    dot: true
  },
  async function(er, files) {
    if (er) {
      console.error(er);
      return;
    }
    await makeDir(path.join(__dirname, ".", "dist"));
    files.forEach(async (item) => {
      const path_ = path.join(__dirname, ".", item);
      const path__ = path.join(__dirname, ".", "dist", item);
      const isFile = fs.statSync(path_).isFile(); //表示是文件
      if (!isFile) {
        //表示是目录，建立
        await makeDir(path__);
      } else {
        const isJs = isJsFile(item);
        const isCss = isCssFile(item);
        const isHtml = isHtmlFile(item);
        if (isJs) {
          // js文件 代码进行压缩
          const content = fs.readFileSync(path_, "utf8");
          try {
            const output = UglifyJS.minify(content, {
              mangle: {
                toplevel: true
              },
              nameCache: {}
            });
            fs.writeFileSync(path__, output.code, "utf8");
            console.log("压缩完成：", item);
          } catch {
            console.log("压缩失败--：", item);
          }
        } else if (isCss) {
          //压缩css文件
          let content = fs.readFileSync(path_, "utf8");
          try {
            content = await formatCss(content);
            const output = new CleanCSS({}).minify(content);
            fs.writeFileSync(path__, output.styles, "utf8");
            console.log("压缩完成：", item);
          } catch {
            console.log("压缩失败--：", item);
          }
        } else if (isHtml) {
          //压缩html文件
          let content = fs.readFileSync(path_, "utf8");
          try {
            content = await formatCss(content, true); //格式化css
            const output = htmlMinifier.minify(content, {
              collapseWhitespace: true, // 删除html里的空格 达到html的压缩
              removeComments: true, //删除html中的注释
              removeCommentsFromCDATA: true, //从脚本和样式删除的注释
              minifyURLs: true,
              minifyJS: (test) => {
                //压缩html中的js
                test = UglifyJS.minify(test, {
                  mangle: {
                    toplevel: true
                  },
                  nameCache: {}
                }).code;
                return test;
              },
              minifyCSS: false //模板引擎的内联样式可能丢失
            });
            fs.writeFileSync(path__, output, "utf8");
            console.log("压缩完成：", item);
          } catch {
            console.log("压缩失败--：", item);
          }
        } else {
          copyFile(path_, path__, (err) => {
            if (err) {
              console.error("创建失败--：", item);
              return;
            }
          });
        }
      }
    });
  }
);
